package com.sikao.app.utils;

import android.util.Base64;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * Created by y50 on 2016/4/20.
 */
public class CryptoUtil {

	public static String time_key;
	public static final String DECODE = "DECODE";
	public static final String ENCODE = "ENCODE";

	public static String getCode(String string, String operation, String key, long expiry) {
		String b = "";
		// 动态密匙长度，相同的明文会生成不同密文就是依靠动态密匙
		int ckey_length = 4;
		if (key == null||key.equals("")) {
			key = time_key.substring(0,10);
		}
		// 密匙
		key = getMD5Str(key);
		// 密匙a会参与加解密
		String keya = getMD5Str(key.substring(0, 16));
		// 密匙b会用来做数据完整性验证
		String keyb = getMD5Str(key.substring(16, 32));
		// 密匙c用于变化生成的密文
		String keyc;
		if (ckey_length > 0) {
			if (operation.equals("DECODE")) {
				keyc = string.substring(0, ckey_length);
			} else {
				keyc = getMD5Str(String.valueOf(System.currentTimeMillis())).substring(32 - ckey_length, 32);
			}
		} else {
			keyc = "";
		}
		String cryptkey = keya + getMD5Str(keya + keyc);
		int key_length = cryptkey.length();
		if (operation.equals("DECODE")) {
			string = getUrldecode1(string.substring(ckey_length,string.length()));
		} else {
			String time = String.valueOf(System.currentTimeMillis()).substring(0, 10);
			if (expiry != 0) {
				expiry += Long.parseLong(time);
				if (expiry > 2147483647) {
					expiry = 2147483647;
				}
				string = expiry + getMD5Str(string + keyb).substring(0, 16) + string;
			}else{
				string = "0000000000" + getMD5Str(string + keyb).substring(0, 16) + string;
			}

		}
		int string_length = string.length();
		String result = "";
		int[] box = new int[256];
		for (int i = 0; i < 256; i++) {
			box[i] = i;
		}
		int[] rndkey = new int[256];
		for (int i = 0; i < 256; i++) {
			rndkey[i] = cryptkey.charAt(i % key_length);
		}
		for (int j = 0, i = 0; i < 256; i++) {
			j = (j + box[i] + rndkey[i]) % 256;
			int tmp = box[i];
			box[i] = box[j];
			box[j] = tmp;
		}

		// 核心加解密部分
		for (int a = 0, j = 0, i = 0; i < string_length; i++) {
			a = (a + 1) % 256;
			j = (j + box[a]) % 256;
			int tmp = box[a];
			box[a] = box[j];
			box[j] = tmp;
			// 从密匙簿得出密匙进行异或，再转成字符
			char a1 = (char)(string.charAt(i) ^ box[(box[a] + box[j]) % 256]);
			result = result + a1;
		}
		if (operation.equals("DECODE")){
			// 验证数据有效性，请看未加密明文的格式
			if (Long.valueOf(result.substring(0, 10))==0||Long.valueOf(result.substring(0,10))
					-Long.valueOf(String.valueOf(System.currentTimeMillis()).substring(0, 10))>0
					&& result.substring(10,26).equals(getMD5Str(result.substring(26,result.length())+keyb).substring(0,16))) {
				return  result.substring(26,result.length());
			} else {
				return "";
			}
		} else {
			// 把动态密匙保存在密文里，这也是为什么同样的明文，生产不同密文后能解密的原因
			// 因为加密后的密文可能是一些特殊字符，复制过程可能会丢失，所以用base64编码
			return keyc+getUrlecode1(result);//.replace("=","")
		}
	}

	public static String getMD5Str(String data) {
		byte[] md5 = null;
		StringBuffer str = null;
		try {
			MessageDigest md5Digest = MessageDigest.getInstance("MD5");
			md5Digest.update(data.getBytes("UTF-8"));
			md5 = md5Digest.digest();
			str = new StringBuffer();
			for (int i = 0; i < md5.length; i++) {
				str.append(String.format("%02x", md5[i]));
			}
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return str.toString();
	}

	// 加密
	public static String getBase64(String str) {
		byte[] b = null;
		String s = null;
		try {
			b = getBytes(str);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		if (b != null) {
			s = new String(Base64.encodeToString(b, Base64.DEFAULT));
		}
		return s;
	}

	private static byte[] getBytes(String str) throws UnsupportedEncodingException {
		return str.getBytes("utf-8");
	}

	// 解密
	public static String getFromBase64(String s) {
		byte[] b = null;
		String result = null;
		if (s != null) {
			try {
				b = Base64.decode(s.getBytes(), Base64.DEFAULT);
				result = new String(b, "utf-8");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return result;
	}

	/**
	 * 将字符串进行UTF—8解码
	 *
	 * @param str
	 * @return
	 */
	public static String getUrldecode1(String str) {
		String result = null;
		try {
			result = URLDecoder.decode(str, "utf-8");
			result.replace("#", "");
			result.replace("%", "");
			result.replace("?", "");
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;
	}

	public static String getUrlecode1(String str) {
		String result = null;
		try {
			result = URLEncoder.encode(str, "utf-8");

		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;
	}
}
